function [weights, error, xAxis] = ...
                supervisedLearn(init_weights, tables, pieces, actions, ...
                        lambda, gamma, eta, max_moves, avgErrorCount)
                        
                      
piecez = 1 : 7;
                    
error = zeros(1, floor(max_moves / avgErrorCount));
xAxis = zeros(1, floor(max_moves / avgErrorCount));

errorTmpIndex = 1;
errorTmp = 0;

exampleNum = length(tables);
exampleIndex = 1;

currentErrorIndex = 1;

weights = init_weights;

for moveCount = 1 : max_moves
    table = tables{exampleIndex};
    piece = pieces(exampleIndex);
    action = actions(exampleIndex);
    
    [inputs, tablez, ~, scaledScores] = formInputs(table, piece);
    
    [quality, neuronOutputs, neuronInputs] = predictQuality(weights, ...
        inputs);

    table = tablez{action};
    scaledScore = scaledScores(action);
    
    nextMoveQuality = estimateNextMoveQuality(table, weights, piecez);
    correctOutput = (1 - gamma) * scaledScore + gamma * nextMoveQuality;
    
    gradients = calculateGradients(weights, neuronOutputs, ...
        neuronInputs, action, correctOutput, lambda);
    weights = calculateNewWeights(weights, gradients, eta);
    
    errorTmp = errorTmp + costFunction(quality(action), correctOutput, weights, ...
        lambda);
    if (errorTmpIndex >= avgErrorCount)
        error(currentErrorIndex) = errorTmp / avgErrorCount;
        xAxis(currentErrorIndex) = moveCount;
        
        disp([num2str(moveCount), ': ', num2str(error(currentErrorIndex))]);
        
        currentErrorIndex = currentErrorIndex + 1;
        
        errorTmp = 0;
        errorTmpIndex = 1;
    else
        errorTmpIndex = errorTmpIndex + 1;
    end
    
    if exampleIndex < exampleNum
        exampleIndex = exampleIndex + 1;
    else
        exampleIndex = 1;
    end
end

end

